/**
 *
 */
package trs.gtfs.parser;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import trs.gtfs.mapper.GtfsRowMapper;
import trs.gtfs.predicate.Predicate;

//XXX test with escaped Quotes and commas "Some String ""OK OK"", and a comma"
//XXX use UTF-8 to read GTFS files.
public abstract class GtfsParser<T extends Object> {
    public void parseFile(final String filename) throws FileNotFoundException {
        parse(new FileInputStream(filename));
    }

    public void parse(final InputStream is) {
        BufferedReader reader = null;

        try {
            parseStart();
            reader = new BufferedReader(new InputStreamReader(is));

            final String header = reader.readLine();

            if (header == null) {
                return;
            } //XXX add error, empty file.

            final String[] headers = header.split(",");
            final GtfsRowMapper<T> mapper = getNewMapper(headers);

            System.out.println(mapper);

            String str = null;

            for (int line = 2; (str = reader.readLine()) != null; line++) {
                final T rowObject = mapper.processRow(str, line);
                processRow(rowObject); //XXX add accumulator field?
            }
        } catch (final IOException e) {
            e.printStackTrace();

            //App.showError(context, "Problems parsing route data", e);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (final IOException e) {
                    //Ignore Exception
                }
            } else if (is != null) {
                try {
                    is.close();
                } catch (final IOException e) {
                    //Ignore Exception
                }
            }

            parseEnd();
        }
    }

    protected void parseStart() {
    }

    protected void parseEnd() {
    }

    protected abstract GtfsRowMapper<T> getNewMapper(String[] headers);

    protected abstract void processRow(T o);

    public abstract List<T> getList();

    public List<T> filter(Predicate<T> p) {
        return filter(getList(), p);
    }

    public List<T> filter(List<T> l, Predicate<T> p) {
        List<T> rval = new ArrayList<T>();

        if (l != null) {
            for (T o : l) {
                if (p.test(o)) {
                    rval.add(o);
                }
            }
        }

        return rval;
    }
}
